package com.github.tvbox.osc.ui.activity.Media

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.github.catvod.utils.Json
import com.github.tvbox.osc.R
import com.github.tvbox.osc.base.BackHandlerHelper
import com.github.tvbox.osc.base.BaseLazyFragment
import com.github.tvbox.osc.base.FragmentBackHandler
import com.github.tvbox.osc.event.PlayEvent
import com.github.tvbox.osc.event.RefreshEvent
import com.github.tvbox.osc.player.controller.VodController
import com.github.tvbox.osc.player.controller.VodController.VodControlListener
import com.github.tvbox.osc.util.PlayerHelper
import com.github.tvbox.osc.viewmodel.SourceViewModel
import com.orhanobut.logger.Logger
import io.github.source.media.bean.MediaBean
import io.github.source.media.bean.MediaPlay
import io.github.source.media.bean.MediaResult
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject
import xyz.doikki.videoplayer.controller.BaseVideoController
import xyz.doikki.videoplayer.player.AbstractPlayer
import xyz.doikki.videoplayer.player.VideoView
import xyz.doikki.videoplayer.player.VideoView.OnStateChangeListener


/**
 * @ClassName: PlayFragment
 * @Description: (播放视窗Fragment)（支持预览 / 全屏播放）
 * @author: huangrongcai
 * @date: 2024/8/22
 *
 * @Copyright: 黄嵘才（HuangRc)
 */
class PlayFragment : BaseLazyFragment(), FragmentBackHandler {
    private val TAG = "App.Media.PlayFragment"
    var mVideoView: VideoView<AbstractPlayer>? = null

    /**
     * 点播控制器（UI）
     */
    private lateinit var mController: VodController
    private val mSourceViewModel by lazy { ViewModelProvider(this).get(SourceViewModel::class.java) }
    private var mPlayLoadTip: TextView? = null
    private var mPlayLoadErr: ImageView? = null
    private var mPlayLoading: ProgressBar? = null

    private var url: String? = null
    private var headers: Map<String?, String?>? = null

    private var mTryBeforeFetchMediaPlay = false

    /**
     * （必要）媒体信息(减少这个在代码的依赖次数）
     */
    var mMediaBean: MediaBean? = null

    /**
     * 点播名称
     */
    private var vodName = ""

    /**
     * 点播ID
     */
    private var vodId = ""

    /**
     * 源站点
     */
    private var siteKey = ""

    /**
     * 点播集的名称
     */
    private var mEpisodeName = ""

    private var flag = ""

    private var episodeIndex = 0
    private var episodeUrl = ""

    // Picture-in-Picture support
    var extPlay = false


    override fun getLayoutResID(): Int {
        return R.layout.fragment_play
    }

    override fun init() {
        initView()
        initViewModel()
    }


    override fun initView() {
        super.initView()
        mVideoView = findViewById(R.id.mVideoView)
        mPlayLoadTip = findViewById<TextView>(R.id.play_load_tip)
        mPlayLoading = findViewById<ProgressBar>(R.id.play_loading)
        mPlayLoadErr = findViewById<ImageView>(R.id.play_load_error)
        setupVideoView()
        setupVodController()
    }

    //设置播放器
    private fun setupVideoView() {
        mVideoView?.addOnStateChangeListener(object : OnStateChangeListener {
            override fun onPlayerStateChanged(playerState: Int) {
                Logger.t(TAG).d("播放器状态 playerState: $playerState")
            }

            override fun onPlayStateChanged(playState: Int) {
                Logger.t(TAG).d("播放状态 playState: $playState")
                if (playState == VideoView.STATE_ERROR) {
                    retryOnPlay()
                    onPlayError()
                }
            }
        })
    }

    /**
     * 设置控制器
     */
    private fun setupVodController() {
        mController = VodController(requireContext())
        //默认配置
        mController.setPlayerConfig(JSONObject())
        setVodController(mController)
        mController.setVodListener(object : VodControlListener {
            override fun playNext(rmProgress: Boolean) {
                togglePlayNext()
            }

            override fun playPrev() {
                togglePlayPrev()
            }

            override fun updatePlayerCfg() {
                Toast.makeText(requireContext(), "变更播放器设置", Toast.LENGTH_SHORT).show()
            }

            override fun replay() {
                onRefresh()
            }

            override fun errReplay() {}
        })
    }

    /**
     * 获取当前播放的媒体名称(含有集数）
     *
     * @return 媒体名称
     */
    fun getName(): String {
        return getVodName() + " " + getEpisodeName()
    }

    /**
     * 获取当前播放的专辑名称
     *
     * @return 专辑名称
     */
    fun getEpisodeName(): String {
        return mEpisodeName
    }

    fun setEpisodeName(text: String) {
        this.mEpisodeName = text
    }

    /**
     * 获取当前播放的媒体名称
     *
     * @return 媒体名称
     */
    fun getVodName(): String {
        return vodName
    }

    private fun getSiteKey(): String {
        return siteKey
    }

    private fun getVodId(): String {
        return vodId
    }

    private fun setVodController(vodController: BaseVideoController) {
        mVideoView?.setVideoController(vodController)
    }


    private fun initViewModel() {
        mSourceViewModel.MediaPlayResult.observeForever { play: MediaResult<MediaPlay?>? ->
            setPlayer(play)
        }
        //播放的消息
        mSourceViewModel.mMediaCallback.observeForever { msg -> Logger.w("onMessage:$msg") }
    }

    /**
     * 播放 MediaResult
     *
     * @param play play 数据
     */
    private fun setPlayer(play: MediaResult<MediaPlay?>?) {
        Logger.t(TAG).d("开始播放 play=$play")
        if (play == null || play.data == null) {
            EventBus.getDefault().post(PlayEvent.PLAY_ERROR)
            return
        }
        val playUrl = play.data?.playUrl
        if (playUrl.isNullOrEmpty()) {
            // 如果播放URL为空，可以直接返回或处理异常
            EventBus.getDefault().post(PlayEvent.PLAY_ERROR)
            return
        }
        val header: Map<String?, String?>
        header = try {
            // 假设Json.toMap()是一个安全的方法，不会返回null，但可能会抛出异常
            // 如果你的库中toMap方法返回null是可能的，请在这里添加null检查
            Json.toMap(play.data?.header)
        } catch (e: Exception) {
            // 处理JSON转换异常，例如记录日志，并返回或进行其他错误处理
            System.err.println("Error parsing JSON header: " + e.message)
            return
        }
        // 调用playUrl方法
        try {
            startPlay(playUrl, header)
        } catch (e: Exception) {
            // 处理播放URL调用中可能出现的异常
            System.err.println("Error playing URL: " + e.message)
        }
    }


    /**
     * 播放这个视频
     *
     * @param bean 数据对象
     */
    fun playOnReady(bean: MediaBean?) {
        mMediaBean = bean
        mTryBeforeFetchMediaPlay = false
        setupToPlayMedia()
    }

    private fun prepareMedia(bean: MediaBean? = mMediaBean): Boolean {
        /*准备播放需要的数据*/
        return if (bean == null) {
            false
        } else try {
            setMediaUrl(bean.vodEpisodeUrl)
            setMediaTitle(bean.vodName)
            setMediaId(bean.vodId)
            setSiteKey(bean.siteKey)
            setEpisodeName(bean.vodEpisodeName)
            flag = bean.vodFlagName
            episodeIndex = bean.vodEpisodeIndex
            true
        } catch (e: Exception) {
            e.printStackTrace()
            Logger.t(TAG).e("播放前准备错误:" + e.message)
            false
        }
    }

    fun setMediaId(vodId: String) {
        this.vodId = vodId
    }

    /**
     * 设置播放媒体地址
     *
     * @param url 地址
     */
    fun setMediaUrl(url: String) {
        episodeUrl = url
    }

    fun setMediaTitle(text: String) {
        vodName = text
    }

    fun setSiteKey(siteKey: String) {
        this.siteKey = siteKey
    }

    private fun togglePlayNext() {
        //通知点播台播放下一个视频
        EventBus.getDefault().post(PlayEvent.PLAY_NEXT(""))
    }

    private fun togglePlayPrev() {
        // 通知选择下一个视频
        EventBus.getDefault().post(PlayEvent.PLAY_PREV(""))
    }

    fun getFlag(): String {
        return flag
    }


    /**
     * 播放视频(默认播放）
     */
    private fun setupToPlayMedia() {
        try {
            /*清理*/
            prepareMedia()
            setPlayTitle()
            setTip("正在解析播放地址", true, false)
            if (shouldTryPlayTheUrl()) {
                return
            }

            //--获取播放地址
            val vodSite = getSiteKey()
            val vodUrl = getVodUrl()
            val vodFlag = getFlag()
            val progressKey = prepareProgressKey(getFlag(), getEpisodeIndex())
            fetchMediaPlay(vodSite, vodFlag, progressKey, vodUrl)
        } catch (e: Exception) {
            Logger.t(TAG).e(e, "播放错误:$e")
        }
    }

    private fun fetchMediaPlay(
        siteKey: String,
        playFlag: String,
        progressKey: String,
        playUrl: String?
    ) {
        if (playUrl.isNullOrEmpty()) {
            setTip("播放地址为空", true, false)
            return
        }
        mSourceViewModel.fetchPlayer(siteKey, playFlag, progressKey, playUrl)
    }


    /**
     * 是否应该尝试播放视频
     *
     * @return true表示应该尝试播放视频，false表示不应该尝试播放视频
     */
    private fun shouldTryPlayTheUrl(): Boolean {
        val vodUrl = getEpisodeUrl()
        if (SourceViewModel.Media.isVideoFormat(vodUrl) && !mTryBeforeFetchMediaPlay) {
            tryPlayUrl(vodUrl, null)
            return true
        }
        return false
    }

    private fun tryPlayUrl(url: String, headers: Map<String?, String?>?) {
        mTryBeforeFetchMediaPlay = true //尝试即时播放
        startPlay(SourceViewModel.Media.getVideoUrl(url), headers)
    }

    fun getEpisodeIndex(): Int {
        return episodeIndex
    }

    /**
     * 获取视频播放地址
     *
     * @return 视频播放地址
     */
    fun getVodUrl(): String {
        return episodeUrl
    }

    /**
     * 获取视频播放地址
     *
     * @return 视频播放地址
     */
    fun getEpisodeUrl(): String {
        return episodeUrl
    }

    override fun onBackPressed(): Boolean {
        //播控管理处理后退事件
        if (mController.onBackPressed()) {
            return true
        }
        return BackHandlerHelper.handleBackPress(this)
    }

    /**
     * 设置播放媒体标题
     */
    private fun setPlayTitle() {
        val playTitleInfo = getName()
        setTitle(playTitleInfo)
    }

    private fun prepareProgressKey(vodFlag: String, episodeIndex: Int): String {
        return getSiteKey() + getVodId() + vodFlag + episodeIndex
    }

    private fun setTitle(text: String) {
        mController.setTitle(text)
    }

    /**
     * 开始播放
     *
     * @param url     媒体的实际播放地址
     * @param headers 媒体的播放头信息（可以为null)
     */
    fun startPlay(url: String?, headers: Map<String?, String?>?) {
        try {
            /*
             *检查，清理，装配，播放
             */
            if (!checkMedia(url, headers)) {
                return
            }
            clearMedia()
            setupMedia(url, headers)
            startMedia(url, headers)
        } catch (e: Exception) {
            e.printStackTrace()
            Logger.t(TAG).e(e, "播放错误:$e")
            EventBus.getDefault().post(PlayEvent.PLAY_ERROR)
        }
    }

    private fun checkMedia(url: String?, headers: Map<String?, String?>?): Boolean {
        if (url == null) {
            EventBus.getDefault().post(PlayEvent.PLAY_ERROR)
            return false
        }
        return true
    }

    private fun clearMedia() {
        //清理
        hideTip()
        mVideoView?.release()
    }

    private fun setupMedia(url: String?, headers: Map<String?, String?>?) {
        PlayerHelper.updateCfg(mVideoView)
        this.url = url
        this.headers = headers
        Logger.t(TAG).d("Media Source url=$url, headers=$headers")
        if (headers != null) {
            mVideoView?.setUrl(url, headers)
        } else {
            mVideoView?.setUrl(url)
        }
    }

    private fun startMedia(url: String?, headers: Map<String?, String?>?) {
        mVideoView?.start()
        mController.resetSpeed()
    }

    fun onPlayError() {
        EventBus.getDefault().post(PlayEvent.PLAY_ERROR)
        //记录出错的播放信息
        val siteKey = getSiteKey()
        Logger.t(TAG).e("播放错误：url=$url, headers=$headers \nsiteKey=$siteKey")
    }

    private fun retryOnPlay() {
        if (mTryBeforeFetchMediaPlay && SourceViewModel.Media.isVideoFormat(getEpisodeUrl())) {
            setupToPlayMedia()
        }
        mTryBeforeFetchMediaPlay = false
    }

    private fun onRefresh() {
        onReset(false)
    }

    private fun onReset() {
    }

    private fun onReset(replay: Boolean) {
        setupToPlayMedia()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun refresh(event: RefreshEvent?) {
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onPlayEvent(event: PlayEvent?) {
    }

    /**
     * 屏幕提示语
     *
     * @param msg     提示语
     * @param loading
     * @param err
     */
    fun setTip(msg: String?, loading: Boolean, err: Boolean) {
        mPlayLoadTip?.text = msg
        mPlayLoadTip?.visibility = View.VISIBLE
        mPlayLoading?.visibility = if (loading) View.VISIBLE else View.GONE
        mPlayLoadErr?.visibility = if (err) View.VISIBLE else View.GONE
    }

    fun hideTip() {
        mPlayLoadTip?.visibility = View.GONE
        mPlayLoading?.visibility = View.GONE
        mPlayLoadErr?.visibility = View.GONE
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        EventBus.getDefault().register(this)
        return super.onCreateView(inflater, container, savedInstanceState)
    }

    override fun onHiddenChanged(hidden: Boolean) {
        if (hidden) {
            if (mVideoView != null) {
                mVideoView?.pause()
            }
        } else {
            if (mVideoView != null) {
                mVideoView?.resume()
            }
        }
        super.onHiddenChanged(hidden)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        //手动注销
        EventBus.getDefault().unregister(this)
        release()
        // 停止磁力下载
        //停止p2p下载
    }

    private fun release() {
        if (mVideoView != null) {
            mVideoView?.release()
            mVideoView = null
        }
    }

    fun hideControl() {
        mController.hide()
    }

    private fun hideInfo() {
        //
    }

    /**
     * 进入全屏播放
     */
    private fun enterFullscreen() {
        //requestFouc

    }
}